<?php
session_start();

class MY_Controller extends CI_Controller {
	var $title = '';
	var $clase_entidad = '';
	var $nombre_controlador = '';
	var $metodo_guardar = 'guardar';
	var $metodo_ver_todos = 'ver_todos';
	var $metodo_busqueda = 'busqueda';
	var $nuevoPermitido = TRUE; 	// Indica si se pueden crear registros nuevos de la entidad. Por defecto, TRUE

	var $CARPETA_VISTAS = '';		// Directorio donde están contenidas las vistas gestionadas por el controlador
	var $pagina_editar = ''; 		// Nombre de la vista de edición
	var $pagina_ver = '';			// Nombre de la vista para mostrar todos
	var $pagina_filtros_ver = '';	// Nombre de la vista con los filtros aplicables a la de mostrar todos

	# Variable utilizada para saber si el usuario actualmente logueado es administrador
	var $userIsAdmin = FALSE;
	var $formatoFechaGuardar = 'Y-m-d';
	
	public function __construct($nombre_controlador, $clase_ent)
    {
    	parent::__construct();
		
		if(isset($_SESSION[$this->template->getRolSessionName()])) {
			$this->userIsAdmin = $this->template->currentUserIsAdmin($_SESSION[$this->template->getRolSessionName()]);
		}

		$this->nombre_controlador = $nombre_controlador;
		$this->clase_entidad = $clase_ent;

		date_default_timezone_set($this->template->getZonaHoraria());
	}

	/* IMPORTANTE: DEBE existir esta función. 
	 * Crea un objeto de la entidad correspondiente según el id especificado. */
	protected function getObjeto($idEntidad = NULL)
	{
		return new $this->clase_entidad($idEntidad);
	}

	/* Método que carga los datos de la entidad para mostrarlos en forma de sólo lectura, acorde al formulario de edición */
	public function visualizar($id_elemento)
	{
		$dataView['objEntidad'] = $this->getObjeto($id_elemento);
		$dataView['soloLectura'] = TRUE;
		$this->_cargarFormEdicion($dataView);
	}

	/* Método para cargar los formularios de creación y actualización de la información de los registros. */
	public function editar($id_elemento = NULL)
	{
		$dataView['objEntidad'] = $this->getObjeto($id_elemento);
		$this->_cargarFormEdicion($dataView);
	}

	/* El método prepara la información necesaria para las vistas de EDICIÓN.
	 * Valida que se pueda realizar la edición antes de continuar. */
	protected function _cargarFormEdicion($dataView, $cargaCompleta = FALSE)
	{
		$obj_entidad = $dataView['objEntidad'];
		$soloLectura = (isset($dataView['soloLectura']) && $dataView['soloLectura']) ? TRUE : FALSE;

		# Datos requeridos por las vistas
		if(!isset($dataView['title'])) {
			$titulo = ($obj_entidad->id == NULL ? 'Nuevo: ' : 'Editar: ') . $this->nombre_entidad;
			if($soloLectura) $titulo = 'Visualizar ' . $this->nombre_entidad;
			$dataView['title'] = $titulo;
		}
		$dataView['nombre_controlador'] = strtolower($this->nombre_controlador);
		if(!isset($dataView['metodo_guardar'])) $dataView['metodo_guardar'] = $this->metodo_guardar;
		$dataView['metodo_ver_todos'] = $this->metodo_ver_todos;
		
		if((!$soloLectura && $this->validarEdicion($obj_entidad->id)) || $soloLectura) {
			# Es posible la edición o creación
			if($cargaCompleta) $dataView['modalDesactivado'] = TRUE;
			
			$dataView = $this->cargarDatosRelacionados($dataView);
			$this->_loadEditView($dataView, $cargaCompleta);
		}
		else {
			$dataView['error'] = 'No es posible editar el elemento seleccionado.';
			$this->ver_todos($dataView);
		}
	}

	/* Carga todas las vistas que conforman la vista de edición	*/
	private function _loadEditView($dataView, $cargaCompleta = TRUE)
	{
		$view_list = array();
		$view_list[] = $this->template->getHeaderEditView();
		if(!isset($dataView['pagina_editar'])) $view_list[] = $this->pagina_editar;
		else $view_list[] = $dataView['pagina_editar'];
		$view_list[] = $this->template->getFooterEditView();

		$this->_loadViews($view_list, $dataView, $cargaCompleta);
	}

	/* Carga todas las vistas que conforman la vista de edición	*/
	protected function _loadFileUploadView($dataView, $cargaCompleta = TRUE)
	{
		$view_list = array();
		$view_list[] = $this->template->getHeaderFileUploadView();
		if(!isset($dataView['pagina_editar'])) $view_list[] = $this->pagina_editar;
		else $view_list[] = $dataView['pagina_editar'];
		$view_list[] = $this->template->getFooterFileUploadView();

		$this->_loadViews($view_list, $dataView, $cargaCompleta);
	}

	/* Valida los datos del formulario en base a las propiedades del modelo al que referencia. */
	public function validarForm($datos = array())
	{	
		if ($datos == array()) $datos = $this->getObjetoDesdeForm();
		
		$objEntidad = $datos['objEntidad'];
		$objRelacionados = $datos['objRelacionados'];
		$objEntidad->validate($objRelacionados);

		if($this->input->is_ajax_request()) echo $objEntidad->error->string;
		else return empty($objEntidad->error->string);
	}

	/* Método para guardar la información del registro. 
	 * Si todo salió correctamente, se muestra el listado de elementos actualizado.
	 * Si hubiera ocurrido un error, se vuelve a cargar el formulario de edición. 
	 * Se realiza aparte para darle a los controladores la posibilidad de sobreescribirlo y realizar
	 * distintas acciones de acuerdo al resultado de la operación. */
	public function guardar()
	{
		$dataView = $this->guardarEntidad();
		if($dataView['error'] != '') {
			// Falló el intento de guardar
			$this->_cargarFormEdicion($dataView, TRUE); 
		}
		else { $this->ver_todos($dataView); }
	}

	/* Guarda los cambios de un modelo o entidad en la BD según corresponda. Devuelve un arreglo con el detalle.
	 * Valida que el objeto cumpla con las restricciones del modelo. Realiza las operaciones a través de transacciones. */
	protected function guardarEntidad($dataView = array())
	{
		if($dataView == array()){
			$datos = $this->getObjetoDesdeForm();
			$objEntidad = $dataView['objEntidad'] = $datos['objEntidad'];
			$objRelacionados = $datos['objRelacionados'];
		}
		else
		{
			$objEntidad = $dataView['objEntidad'];
			$objRelacionados = $dataView['objRelacionados'];
			
			$datos = array();
			$datos['objEntidad'] = $objEntidad;
			$datos['objRelacionados'] = $objRelacionados;
		}

		# Se manejan transacciones para interactuar con la BD
		$objEntidad->trans_begin();
		$operacion_exitosa = $objEntidad->save($objRelacionados);
		#if(!$operacion_exitosa && !$objEntidad->valid)
		if(!$operacion_exitosa && !$this->validarForm($datos))
		{ 
			# Falló la validación de datos de acuerdo a las reglas de los modelos
			$dataView['error'] = $objEntidad->error->string; 
		}
		else
		{
			if ($objEntidad->trans_status() === FALSE) # Si la transacción falló, hago un rollback 
				$objEntidad->trans_rollback();
			else # Transacción exitosa, realizo el commit 
				$objEntidad->trans_commit();

			# Almaceno todos los errores que hubieran podido ocurrir
			$dataView['error'] = $objEntidad->error->string;
		}

		return $dataView;
	}

	/* Se utiliza una función PROTEGIDA para obligar a los controladores a que hagan específico el método
	 * sólo si se requiere. */
	public function eliminar($id_elemento)
	{
		$dataView['title'] = 'Eliminar elemento';
		$dataView['error'] = '';

		if($this->validarEliminacion($id_elemento))
		{
			# Se obtiene el objeto que se desea eliminar
			$objEntidad = $this->getObjeto($id_elemento);
			
			# Se manejan transacciones para interactuar con la BD
			$objEntidad->trans_begin();
			$objEntidad->delete();
			if ($objEntidad->trans_status() === FALSE) # Se chequea el estado de la transacción. Si falló, hago un rollback
			    $objEntidad->trans_rollback();
			else  # Transacción exitosa, realizo el commit
				$objEntidad->trans_commit();

			# Almaceno todos los errores que hubieran podido ocurrir
			$dataView['error'] = $objEntidad->error->string;
			$this->ver_todos($dataView);
		}
		else
		{
			$dataView['error'] = 'No se puede eliminar el elemento elegido.';
			$dataView['path_volver'] = $this->nombre_controlador . '/' . $this->metodo_ver_todos;
			$this->_loadViews($this->template->getErrorMessageView(), $dataView);
		}
	}

	/* Método auxiliar que permite borrar varios elementos juntos (generalmente utilizado para eliminar
		elementos relacionados) */
	protected function eliminarTodos($objetos)
	{	
		# Se manejan transacciones para interactuar con la BD
		$objetos->trans_begin();
		$objetos->delete_all();
		if ($objetos->trans_status() === FALSE) # Se chequea el estado de la transacción. Si falló, hago un rollback
		    $objetos->trans_rollback();
		else  # Transacción exitosa, realizo el commit
			$objetos->trans_commit();

		# Almaceno todos los errores que hubieran podido ocurrir
		return $objetos->error->string;
	}

	/* Carga todas las vistas que conforman la página VER TODOS (Listdado)	*/
	private function _loadVerTodosView($dataView, $cargaCompleta = TRUE)
	{
		$view_list = array();
		$view_list[] = $this->template->getHeaderVerTodosView();
		
		if(!isset($dataView['sin_filtros']) || !$dataView['sin_filtros']) $view_list[] = $this->pagina_filtros_ver;

		$view_list[] = $this->template->getMiddleVerTodosView();

		if(!isset($dataView['pagina_ver'])) $view_list[] = $this->pagina_ver;
		else $view_list[] = $dataView['pagina_ver'];

		$view_list[] = $this->template->getFooterVerTodosView();

		$this->_loadViews($view_list, $dataView, $cargaCompleta);
	}

	


	/* Carga todas las vistas que conforman la página de BÚSQUEDA	*/
	private function _loadBusquedaView($dataView)
	{
		$view_list = array();
		$view_list[] = $this->template->getHeaderBusquedaView();
		if($this->pagina_filtros_ver != '') $view_list[] = $this->pagina_filtros_ver;
		$view_list[] = $this->template->getMiddleBusquedaView();
		$view_list[] = $this->pagina_ver;
		$view_list[] = $this->template->getFooterBusquedaView();

		$this->_loadViews($view_list, $dataView, FALSE);
	}

	/* Carga todos los registros de un modelo o entidad (de acuerdo a los filtros o los últimos agregados) */
	public function ver_todos($dataView = array())
	{
		$entidad_plural = isset($dataView['entidad_plural']) ? $dataView['entidad_plural'] : '';
		if ($entidad_plural == '') $entidad_plural = $this->nombre_entidad . 's';

		if(!isset($dataView['title'])) $dataView['title'] = 'Listado de ' . $entidad_plural;
		$dataView['nombre_controlador'] = strtolower($this->nombre_controlador);
		if(!isset($dataView['metodo_filtrar'])) $dataView['metodo_filtrar'] = $this->metodo_ver_todos;
		if(!isset($dataView['permitir_agregar_nuevo'])) $dataView['permitir_agregar_nuevo'] = $this->nuevoPermitido;
		$dataView['es_busqueda'] = FALSE;
		$dataView['realizar_paginacion'] = TRUE;

		if(!isset($dataView['error'])) $dataView['error'] = '';
		$dataView = $this->filtrar($dataView);

		// Se cargan los datos relacionados para los filtros
		$dataView = $this->cargarDatosRelacionados($dataView);
		$this->_loadVerTodosView($dataView);
	}



//METODOS DEL PANEL
/* Carga todos los registros de un modelo o entidad (de acuerdo a los filtros o los últimos agregados) */
	public function ver_panel($dataView = array())
	{
		$entidad_plural = isset($dataView['entidad_plural']) ? $dataView['entidad_plural'] : '';
		if ($entidad_plural == '') $entidad_plural = $this->nombre_entidad . 's';

		if(!isset($dataView['title'])) $dataView['title'] = 'Panel de Suministro';
		$dataView['nombre_controlador'] = strtolower($this->nombre_controlador);
		if(!isset($dataView['metodo_filtrar'])) $dataView['metodo_filtrar'] = 'ver_panel';
		if(!isset($dataView['permitir_agregar_nuevo'])) $dataView['permitir_agregar_nuevo'] = $this->nuevoPermitido;
		//$dataView['es_busqueda'] = FALSE;
		//$dataView['realizar_paginacion'] = TRUE;

		if(!isset($dataView['error'])) $dataView['error'] = '';
		$dataView = $this->filtrar($dataView);

		// Se cargan los datos relacionados para los filtros
		$dataView = $this->cargarDatosRelacionados($dataView);
		$this->_loadVerPanelView($dataView);
	}

/* Carga todas las vistas que conforman la página VER TODOS (Listdado)	*/
	private function _loadVerPanelView($dataView, $cargaCompleta = TRUE)
	{
		$view_list = array();
		$view_list[] = $this->template->getHeaderPanelView();
		
		//if(!isset($dataView['sin_filtros']) || !$dataView['sin_filtros']) $view_list[] = $this->pagina_filtros_ver;

		$view_list[] = $this->template->getMiddleVerPanelView();

		if(!isset($dataView['pagina_ver'])) $view_list[] = $this->pagina_ver;
		else $view_list[] = $dataView['pagina_ver'];

		$view_list[] = $this->template->getFooterVerTodosView();

		$this->_loadViews($view_list, $dataView, $cargaCompleta);
	}
	



	/* Carga todos los registros de un modelo o entidad (de acuerdo a los filtros o los últimos agregados) */
	public function busqueda()
	{
		$dataView['es_busqueda'] = TRUE;
		$dataView['title'] = 'Buscar...';
		$dataView['nombre_controlador'] = strtolower($this->nombre_controlador);
		$dataView['metodo_filtrar'] = $this->metodo_busqueda;
		$dataView['realizar_paginacion'] = TRUE;

		$dataView = $this->filtrar($dataView);

		// Se cargan los datos relacionados para los filtros
		$dataView = $this->cargarDatosRelacionados($dataView);
		$this->_loadBusquedaView($dataView);
	}

	public function filtrar($dataView = array())
	{
		$dataView = $this->_aplicarFiltros($dataView);
		$objEntidad = $dataView['objEntidad'];

		if($dataView['detalle_filtros'] != '')
			$dataView['detalle_filtros'] = 'Filtros aplicados: ' . $dataView['detalle_filtros'];

		if(isset($dataView['realizar_paginacion']) && $dataView['realizar_paginacion']) {
			$pagina = $this->input->post('hidden_page') ? $this->input->post('hidden_page') : 1;
			$dataView['listado'] = $objEntidad->get_paged_iterated($pagina, 15);
		}
		else $dataView['listado'] = $objEntidad->get_iterated();
		
		return $dataView;
	}

	/* Filtra los datos y devuelve sólo código y nombre. IMPRIME el resultado con JSON, para AJAX */
	public function busqueda_rapida()
	{
		$dataView = $this->filtrar();
		$opciones = array();
		foreach ($dataView['listado'] as $objEntidad) {	
			$opciones[$objEntidad->id] = $objEntidad->nombre;
		}
		
		if($this->input->is_ajax_request()) {
			$json = json_encode($opciones);
			echo $json;
		}
		else return $opciones;
	}
	
	/* Carga las vistas de acuerdo a cierto orden establecido para el sitio actual (cabecera, cuerpo, pie) */
	protected function _loadViews($view, $dataView, $cargaCompleta = TRUE)
	{
		if(!isset($dataView['title']) || $dataView['title'] == '') $dataView['title'] = $this->title;
		if(!isset($dataView['error'])) $dataView['error'] = '';
        
        # Valido la sesión del usuario (si correspondiera)
        $dataView = $this->_establecerDatosSesion($dataView);
        if (!$dataView['usuarioLogueado']) {
			$dataView['nombre_controlador'] = 'user_login';
			$dataView['metodo_validacion'] = 'validarUsuario';
			$view = $this->template->getLoginView();
        }
		
		# Cuando el método se llama desde AJAX, se debe cargar sólo la página con el contenido
		if(isset($dataView['cargaCompleta'])) $cargaCompleta = $dataView['cargaCompleta'];
		if($this->input->is_ajax_request()) $cargaCompleta = FALSE;

		$view_list = array();
		if($cargaCompleta)
		{
			$view_list[] = $this->template->getHeaderView();
			$view_list[] = $this->template->getMenuView();
			
			if(is_array($view)) $view_list = array_merge($view_list, $view);
			else $view_list[] = $view;
			
			$view_list[] = $this->template->getFooterView();
		}
		else {
			if(is_array($view)) $view_list = $view;
			else $view_list[] = $view;
		}

		foreach ($view_list as $simple_view) {
			if($simple_view != '') $this->load->view($simple_view, $dataView);
		}
	}

	/* Valida si existe un usuario logueado para el sistema (si estuviera habilitado el módulo
		correspondiente) */
	private function _establecerDatosSesion($dataView)
	{
		$usuarioLogueado = FALSE;
		if($this->template->loginModuleEnabled())
		{
			# Está habilitado el uso del módulo de usuarios
			if(isset($_SESSION[$this->template->getProyectSessionName()])){
				$dataView['urlLogin'] = 'user_login/logout';
				$dataView['username'] = $_SESSION[$this->template->getUsernameSessionName()];
				$dataView['user_rol'] = $_SESSION[$this->template->getRolSessionName()];
				$dataView['id_user'] = $_SESSION[$this->template->getIdUserSessionName()];
				$dataView['imgPerfilUser'] = $_SESSION[$this->template->getImgSessionName()];
				$usuarioLogueado = TRUE;
			}
		}
		else {
			# Al estar inhabilitado el uso del módulo de usuarios, seteo valores por defecto para el uso
			# ilimitado del sitio
			$usuarioLogueado = TRUE;
			$_SESSION[$this->template->getRolSessionName()] = 'ADMIN';
			$dataView['urlLogin'] = '';
		}

		$dataView['usuarioLogueado'] = $usuarioLogueado;
		return $dataView;
	}

	/** Llamada desde AJAX para mostrar un resumen de un objeto */
	public function toString($id_elemento, $datos = '', $objEntidad = NULL)
	{
		if ($datos == '') $datos = 'Código interno: ' . $id_elemento;

		if($this->input->is_ajax_request()) echo "<pre><p>$datos</p></pre>";
		else return $datos;
	}

	/** Llamada desde AJAX para mostrar un resumen de un objeto */
	public function cargarSegunFiltro($nombre, $codigo)
	{
		$objEntidad = $this->getObjeto();
		
		if($nombre != '-' || $codigo != 0) {
			if($codigo != '') $objEntidad->where('id', $codigo);
			if($nombre != '') $objEntidad->like('nombre', $nombre);

			$objEntidad->limit(1);
			$objEntidad->order_by('id', 'desc');
			$objEntidad->get();

			$this->toString($objEntidad->id, '', $objEntidad);
		}
		else {
			if($this->input->is_ajax_request()) echo "<pre><p>Debe ingresar filtros de búsqueda antes de continuar</p></pre>";
			else return 'Debe ingresar filtros de búsqueda antes de continuar';
		}
	}

	
	/**
	 * Verifica si el usuario puede realizar o no una acción de acuerdo a su rol.
	 * 
	 * Recibe como parámetros el controlador y la función a la que se desean acceder para validar los permisos del usuario actual.
	 */	
	protected function permitted($controller, $function) {
		if($this->template->loginModuleEnabled()) 
		{
			$permitted = FALSE;
			
			if(isset($_SESSION[$this->template->getPermissionSessionName()])) {
				// Obtengo los permisos para el usuario actual según su rol
				$permissions = $_SESSION[$this->template->getPermissionSessionName()];
				if(is_array($permissions)) {
					foreach($permissions as $perm) {
						$arregloPermiso = explode('/', $perm);
						if(count($arregloPermiso) > 1) {
							$controlador = $arregloPermiso[0];
							$funcion = $arregloPermiso[1];
							// El formato de los permisos es controlador/funcion. Si el controlador coindice, valido sus permisos
							if($controlador === $controller) {
								if($funcion === '*') return TRUE; // Si el permiso es controlador/* significa que tiene acceso a todas las acciones
								else {
									$metodo = $controller . '/' . $function;
									if ($perm === $metodo) return TRUE;
								}
							}
						}
					}
				}
			}
			return $permitted;
		}
		else return TRUE;
	}
	
	protected function sendMail($to, $from_name, $from_mail, $subject, $message)
	{
		$this->load->library('mail');
		return $this->mail->sendMail($to, $from_name, $from_mail, $subject, $message);
	}

	public function borradoPosible($id_elemento)
	{	
		// La función está IMPRIMIENDO la respuesta, para que pueda obtenerse desde AJAX
		if($this->validarEliminacion($id_elemento)) echo TRUE;
		else echo FALSE;
	}

	public function edicionPosible($id_elemento)
	{	
		// La función está IMPRIMIENDO la respuesta, para que pueda obtenerse desde AJAX
		if($this->validarEdicion($id_elemento)) echo TRUE;
		else echo FALSE;
	}

	protected function limpiarCaracteresEspeciales($string) {
		 $string = htmlentities($string);
		 $string = preg_replace('/\&(.)[^;]*;/', '\\1', $string);
		 return $string;
	}

	public function fechaFormatoBD($fecha)
		 {
		  if($fecha != '') {
		   $fecha = str_replace("-", "/", $fecha);
		         $partes_fecha = explode("/", $fecha); # Formato de fecha: DD/MM/AAAA
		         
		            # El formato de la fecha para guardar es AAAA-MM-DD
		            $fecha = $partes_fecha[2] . '/' . $partes_fecha[1] . '/' . $partes_fecha[0];
		   $fecha = strtotime($fecha);
		         $fecha = ($fecha != FALSE) ? date($this->formatoFechaGuardar, $fecha) : '';
		      
		         if($fecha != '')
		         {
		             $date = DateTime::createFromFormat($this->formatoFechaGuardar, $fecha);
		             $fecha = $date->format($this->formatoFechaGuardar);
		         }
		     }
		  return $fecha;
		 }

	public function generar_excel($dataView = array())
	{	
		# Defino el título del documento
		$entidad_plural = isset($dataView['entidad_plural']) ? $dataView['entidad_plural'] : ($this->nombre_entidad . 's');
		if(!isset($dataView['title'])) $dataView['title'] = 'Listado de ' . $entidad_plural;
		
		# Obtengo los datos a mostrar
		if(!isset($dataView['listado'])) {
			$dataView['realizar_paginacion'] = FALSE;
			$dataView = $this->filtrar($dataView);
		}
		$listado = $dataView['listado'];

		if($listado->exists()) {
			# Cargo las configuraciones de exportación de datos a Excel
			$config = new Conf_exportar_excel();
			$config->get(1);

			$this->load->library('to_excel');
			$objPHPExcel = $this->to_excel->getExcelObject($dataView['title']);
			
			# Defino las cabeceras del documento (logo de la empresa, nombre, fecha)
			if ($config->mostrar_logo) {
				$path_logo = !empty($config->logo) ? $config->logo : 'logo_empresa.png';
				$this->to_excel->setImagen($objPHPExcel, $config->logo_celdaInicio, $config->logo_celdaFin, $path_logo);
			}

			if($config->mostrar_empresa) {
				$this->to_excel->setEmpresa($objPHPExcel, $config->empresa_celdaInicio, $config->empresa_celdaFin, $config->conf_configuracion->get()->empresa);
			}

			if($config->mostrar_titulo) {
				$this->to_excel->setTituloInforme($objPHPExcel, $config->titulo_celdaInicio, $config->titulo_celdaFin, $dataView['title']);
			}
			
			if ($config->mostrar_fecha) {
				$this->to_excel->setFecha($objPHPExcel, $config->fecha_celdaInicio, $config->fecha_celdaFin);
			}

			# Seteo las cabeceras de la tabla de datos
			if(isset($dataView['headers_datos'])) {
				$objPHPExcel->getActiveSheet()->fromArray($dataView['headers_datos'], NULL, $config->cabecera_celdaInicio);
			}

			# Defino el ancho de las columnas de manera automática, y pongo los títulos en negrita
			$cant_columnas = count($dataView['headers_datos'])-1;
			for ($col = 0; $col <= $cant_columnas; $col++) {
				$letra = PHPExcel_Cell::stringFromColumnIndex($col);
				$objPHPExcel->getActiveSheet()->getColumnDimension($letra)->setAutoSize(true);

				if($col == 0) $primera_letra = $letra;
				if($col == $cant_columnas) $ultima_letra = $letra;
			}
			if ($cant_columnas > 0) {
				$fila = PHPExcel_Cell::coordinateFromString($config->cabecera_celdaInicio);
				$header_range = $primera_letra . $fila[1] . ':' . $ultima_letra . $fila[1];
				$objPHPExcel->getActiveSheet()->getStyle($header_range)->getFont()->setBold(true);
			}

			# Seteo los datos de la tabla
			if(isset($dataView['datos_campos'])) {
				$datos = array();
				foreach ($listado as $objEntidad) {
					$datos_entidad = array();
					foreach ($dataView['datos_campos'] as $campo => $datosCampo) { 
						if(empty($datosCampo)) $datos_entidad[] = $objEntidad->{$campo};
						else {
							if ($datosCampo == 'bool') {
								$valor = $objEntidad->{$campo};
								$datos_entidad[] = ($valor || $valor == 1) ? 'Sí' : 'No';
							}
							else { 
								$clasePadre = $objEntidad;
								$claseHija = NULL;
								foreach ($datosCampo as $clase) {
									$claseHija = new $clase($clasePadre->{$clase . "_id"});
									$clasePadre = $claseHija;
								}
								
								if($claseHija != NULL) $datos_entidad[] = $claseHija->{$campo};
								
								//$objCampo = new $datosCampo($objEntidad->{$datosCampo . "_id"});
								//$datos_entidad[] = $objCampo->{$campo};
							}
						}
					}

					$datos[] = $datos_entidad;
				}

				$objPHPExcel->getActiveSheet()->fromArray($datos, NULL, $config->datos_celdaInicio);
			}

			// Establecer la hoja activa, para que cuando se abra el documento se muestre primero.
			$objPHPExcel->setActiveSheetIndex(0);

			$xlsx = $dataView['xlsx'] = $config->excel2007oMayor;
			$excel = $xlsx ? 'Excel2007' : 'Excel5';
			$dataView['objWriter'] = $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, $excel);
			$dataView['objPHPExcel'] = $objPHPExcel;

			$this->load->view('reportes/report_view', $dataView);
		}
		else { 
			$dataView['error'] = 'La consulta no produjo resultados.';
			$this->informe($dataView);
		}
	}
}